home *** CD-ROM | disk | FTP | other *** search
- #include <lisp.h>
- #include <loader.h>
-
- /*
- When you do a Set Project Type…, you should
- fill in the dialog fields in the following way:
-
- Project Type -> Code Resource (the radio button)
- File Type -> As you wish
- Creator -> As you wish
- Multi-Segment -> As you wish
- Name -> The name of your module (as expected by DEFCMODULE)
- Type -> TCCD
- Id -> As you wish (63 or lower if multi-segmented)
- Attrs -> 10 (only check the Locked menu item)
- Custom Header -> Unchecked
- */
-
- /*
- If one of your function wants to return a value,
- it has to be of type long. That's because ThinkC
- returns result values in D0 and MCL reads a D0
- returned value as a long.
-
- If your function wants to return a pointer, you
- can use the RETURN_A0 macro defined in <lisp.h>.
- */
-
- /*
- When MCL passes a Lisp object, it passes a pointer to it.
- That's why you need to use the GET macro to get to the actual Lisp object.
-
- MCL's fixnums are shifted by 3 bits (we say they are boxed).
- That's why you need to use to UNBOX macro to get the actual value.
-
- When you return a value (in D0), you don't need to BOX it first, as MCL
- will do it for you when your FF-CALL exits.
- */
-
- long testFixnum (long ptr)
- {
- return(UNBOX(GET(ptr)) + 1);
- }
-
- long testCharacter (long ptr)
- {
- switch (CHARACTER(GET(ptr))) {
- case 'a': return 1; break;
- case 'b': return 2; break;
- case 'c': return 3; break;
- default: return 4;
- }
- }
-
- void testList (long ptr)
- {
- long list = GET(ptr);
-
- CAR(list) += 8;
- CDR(list) = CDR(CDR(list));
- }
-
- struct foo {
- long a, b, c;
- };
-
- void testStruct (long ptr)
- {
- struct foo *s = STRUCTURE(GET(ptr),foo);
-
- /*
- As we are playing in MCL's back, we need to BOX our integers.
- */
-
- s->a += BOX(1);
- s->b += BOX(2);
- s->c += BOX(3);
- }
-
- /*
- Passing multi-dimentionnal arrays to C would be
- very awkward because MCL implements multi-dimentionnal
- arrays as displaced arrays.
- */
-
- void testVector (long ptr)
- {
- int i;
- long *vec = VECTOR(GET(ptr));
-
- for(i=0; i<5; i++) {
- vec[i] += BOX(i);
- }
- }
-
- /*
- A string is simply a vector of characters,
- each one taking one byte of memory.
- */
-
- void testString (long ptr)
- {
- int i;
- char *str = STRING(GET(ptr));
-
- for(i=0; i<STRING_SIZE(GET(ptr)); i++) {
- if (str[i] == 'a')
- str[i] = 'A';
- }
- }
-
- void testShortDouble (long ptr)
- {
- short double *x = FLOAT(GET(ptr));
- *x = *x + 1.2;
- }
-
- void testDouble (double *x)
- {
- *x = *x + 1.2;
- }
-
- /*
- If you allocate your structures 'a la' C, then your C code
- becomes very nice and efficient (but see the THOUGHTS file for drawbacks).
- */
-
- struct myStruct {
- long a, b, c;
- };
-
- void testCStructures (struct myStruct *ptr)
- {
- ptr->c += ptr->a + ptr->b;
- }
-
- void testA0 (char *ptr)
- {
- RETURN_A0(ptr+1);
- }
-
- long testCallback (long ptr, void (*lispfn) ())
- {
- (*lispfn) ();
- return(UNBOX(CAR(GET(ptr))));
- }
-
- long myLong = 11;
- double myDouble = 0.23;
-
- long testGlobals ()
- {
- return( myLong * myLong );
- }
-
- extern testMultiSegment();
-
- void testTraps()
- {
- RETURN_A0(NewPtr(12));
- }
-
- /*
- If the names match, the EXPORT macro returns the
- address of the function in the A0 register.
-
- If no EXPORT is successfull then the LOADER_ERROR
- macro returns a NIL pointer in A0.
- */
-
- main (unsigned char name[])
- {
- EXPORT(name, myLong, "\pMY-LONG");
- EXPORT(name, myDouble, "\pMY-DOUBLE");
-
- EXPORT(name, testFixnum, "\pTEST-FIXNUM");
- EXPORT(name, testCharacter, "\pTEST-CHARACTER");
- EXPORT(name, testList, "\pTEST-LIST");
- EXPORT(name, testStruct, "\pTEST-STRUCT");
- EXPORT(name, testVector, "\pTEST-VECTOR");
- EXPORT(name, testString, "\pTEST-STRING");
- EXPORT(name, testShortDouble, "\pTEST-SHORT-DOUBLE");
- EXPORT(name, testDouble, "\pTEST-DOUBLE");
- EXPORT(name, testCStructures, "\pTEST-C-STRUCTURES");
- EXPORT(name, testA0, "\pTEST-A0");
- EXPORT(name, testCallback, "\pTEST-CALLBACK");
- EXPORT(name, testGlobals, "\pTEST-GLOBALS");
- EXPORT(name, testMultiSegment, "\pTEST-MULTI-SEGMENT");
- EXPORT(name, testTraps, "\pTEST-TRAPS");
-
- LOADER_ERROR();
- }
-